#include "Book_t.h"
#include "Borrower_t.h"
#include <algorithm>
using namespace std;

Book_t::Book_t(Book& b, ISBN isbn, unsigned int copies) : book(b), isbn(isbn), copies(copies){
}

Book_t::Book_t(const Book_t &b) : book(b.book){
	this->isbn = b.isbn;
	this->copies = b.copies;
}

Book_t::~Book_t(){
}

bool Book_t::available() const{
	return this->copies > 0;
}

bool Book_t::borrow(Borrower_t *borrower){
	if(available()){
		//Only borrow book if is available
		this->borrowers.push_back(borrower);
		this->copies--;
		return true;
	}else{
		//Register to waiting list
		this->waiting.push_back(borrower);
	}
	return false;
}

bool Book_t::bringBack(Borrower_t *borrower){
	list<const Borrower_t*>::iterator it = find(borrowers.begin(),borrowers.end(),borrower);
	if(it == borrowers.end()){
		//This book is not borrowed by the borrower
		return false;
	}
	this->copies++;
	this->borrowers.remove(borrower);
	if(this->waiting.size() > 0){
		//Give this book to the first waiting
		list<const Borrower_t *>::const_iterator firstBorrower = this->waiting.begin();
		this->borrowers.push_back(*firstBorrower);
		this->waiting.pop_back();
	}
	return true;
}

ostream& operator<<(ostream& os, const Book_t& book){
	os << book.book << "ISBN: " << book.isbn << " Copies left: " << book.copies << endl;
	os << "Book borrowes: ";
	if(book.borrowers.size() > 0){
		os << endl;
		int count = 1;
		list<const Borrower_t*>::const_iterator it;
		for(it=book.borrowers.begin();it!=book.borrowers.end();++it){
			os << "\t" << count << ": " << (**it).getID() << " " << (**it).getName() << endl;
			++count;
		}
	}else{
		os << "[empty]" << endl;
	}
	os << "Waiting borrowers: ";
	if(book.waiting.size() > 0){
		os << endl;
		int count = 1;
		list<const Borrower_t*>::const_iterator it;
		for(it=book.waiting.begin();it!=book.waiting.end();++it){
			os << "\t" << count << ": " << (**it).getID() << " " << (**it).getName() << endl;
			++count;
		}
	}else{
		os << "[empty]" << endl;
	}
	return os;
}

const string& Book_t::getISBN() const{
	return this->isbn;
}

const Person* Book_t::getAuthor() const{
	return this->book.getAuthor();
}
const string& Book_t::getTitle() const{
	return this->book.getName();
}

bool Book_t::isBorrowed() const{
	return !borrowers.empty();
}